package com.motong.gongdan.controller.system;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.motong.gongdan.config.CustomCellWriteHandler;
import com.motong.gongdan.config.ResponseData;
import com.motong.gongdan.config.auth.UserLoginToken;
import com.motong.gongdan.constant.CommonConstant;
import com.motong.gongdan.entity.*;
import com.motong.gongdan.enums.ObjectType;
import com.motong.gongdan.service.*;
import com.motong.gongdan.util.*;
import com.motong.gongdan.vo.resp.*;
import com.motong.gongdan.vo.system.otherVo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author:fff
 * @time:2022/3/9
 */
@RestController
@Api(value = "统计报表", tags = {"统计报表"})
@RequestMapping(value = "/sys/statistics")
public class StatisticsController {
    @Resource
    WorkReportService workReportService;
    @Resource
    DepartmentsService departmentsService;
    @Resource
    WorkOrderService workOrderService;
    @Resource
    ProcessesService processesService;
    @Resource
    UserService userService;
    @Resource
    ReportBadProductService reportBadProductService;
    @Resource
    BadProductService badProductService;
    @Resource
    CustomFieldService customFieldService;

    @UserLoginToken
    //@H5LoginToken
    @ApiOperation(value = "产量统计")
    @RequestMapping(value = "yield_list", method = RequestMethod.POST)
    public ResponseData yieldList(@RequestBody YieldListVo vo) {
        IPage<YieldListResp> data = null;
        if (vo.getType().equals("product")) {
            data = workReportService.getBaseMapper().getYieldForProduct(new Page<YieldListResp>(vo.getPage(), vo.getLimit())
                    , new QueryWrapper<YieldListResp>()
                            .isNotNull("p.name")
                            .between(vo.getReportStartTimeStart() != null && vo.getReportStartTimeEnd() != null,
                                    "c.actual_start_time", vo.getReportStartTimeStart(), vo.getReportStartTimeEnd())
                            .between(vo.getReportEndTimeStart() != null && vo.getReportEndTimeEnd() != null,
                                    "c.actual_end_time", vo.getReportEndTimeStart(), vo.getReportEndTimeEnd())
                            .between(vo.getActualStartTime() != null && vo.getActualEndTime() != null,
                                    "wr.report_start_time", vo.getActualStartTime(), vo.getActualEndTime())
                            .like(StringUtil.isNotBlank(vo.getWorkOrderCode()), "c.work_order_code", vo.getWorkOrderCode())
                            .like(StringUtil.isNotBlank(vo.getProductCode()), "c.product_code", vo.getProductCode())
                            .like(StringUtil.isNotBlank(vo.getProductName()), "p.name", vo.getProductName())
                            .in(!CollectionUtils.isEmpty(vo.getProduceUser()), "wr.produce_user", vo.getProduceUser())
                            .in(!CollectionUtils.isEmpty(vo.getProcessCode()), "c.process_code", vo.getProcessCode()));
        } else if (vo.getType().equals("process")) {
            data = workReportService.getBaseMapper().getYieldForProcess(new Page<YieldListResp>(vo.getPage(), vo.getLimit()),
                    new QueryWrapper<YieldListResp>()
                            .between(vo.getReportStartTimeStart() != null && vo.getReportStartTimeEnd() != null,
                                    "c.actual_start_time", vo.getReportStartTimeStart(), vo.getReportStartTimeEnd())
                            .between(vo.getReportEndTimeStart() != null && vo.getReportEndTimeEnd() != null,
                                    "c.actual_end_time", vo.getReportEndTimeStart(), vo.getReportEndTimeEnd())
                            .between(vo.getActualStartTime() != null && vo.getActualEndTime() != null,
                                    "wr.report_start_time", vo.getActualStartTime(), vo.getActualEndTime())
                            .like(StringUtil.isNotBlank(vo.getWorkOrderCode()), "c.work_order_code", vo.getWorkOrderCode())
                            .like(StringUtil.isNotBlank(vo.getProductCode()), "c.product_code", vo.getProductCode())
                            .like(StringUtil.isNotBlank(vo.getProductName()), "p.name", vo.getProductName())
                            .in(!CollectionUtils.isEmpty(vo.getProduceUser()), "wr.produce_user", vo.getProduceUser())
                            .in(!CollectionUtils.isEmpty(vo.getProcessCode()), "c.process_code", vo.getProcessCode())
                            .groupBy("c.process_code,p.code"));
        }
        if (vo.getActualStartTime() == null) {
            vo.setActualStartTime(new Date());
        }
        if (vo.getActualEndTime() == null) {
            vo.setActualEndTime(new Date());
        }
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            List<YieldListResp> records = data.getRecords();
            records.removeAll(Collections.singleton(null));
            records.forEach(d -> {
                List<YieldTimeResp> dateList = workReportService.getBaseMapper().getDateByTime(TimeUtil.getDateDefaultStringTwo(vo.getActualStartTime()), TimeUtil.getDateDefaultStringTwo(vo.getActualEndTime()), d.getMissionIds());
                if (!CollectionUtils.isEmpty(dateList)) {
                    if (vo.getTimeType().equals("day") || StringUtil.isBlank(vo.getTimeType())) {
                        d.setList(dateList);
                    } else {
                        Map<String, Object> map = new HashMap<>();
                        map.put("startDate", TimeUtil.getDateDefaultStringTwo(vo.getActualStartTime()));
                        map.put("endDate", TimeUtil.getDateDefaultStringTwo(vo.getActualEndTime()));
                        try {
                            List<String> timeList = new ArrayList<>();
                            if (vo.getTimeType().equals("week")) {
                                timeList = TimeUtil.doDateByStatisticsType("week", map);
                            } else if (vo.getTimeType().equals("month")) {
                                timeList = TimeUtil.doDateByStatisticsType("month", map);
                            }
                            if (!CollectionUtils.isEmpty(timeList)) {
                                List<YieldTimeResp> dateListWeek = new ArrayList<>();
                                for (int i = 0; i < timeList.size(); i += 2) {
                                    YieldTimeResp ytr = new YieldTimeResp();
                                    ytr.setTime(timeList.get(i) + "~" + timeList.get(i + 1));
                                    List<YieldTimeResp> list1 = workReportService.getBaseMapper().getDateByTime(timeList.get(i), timeList.get(i + 1), d.getId().toString());
                                    Integer count = list1.stream().collect(Collectors.summingInt(YieldTimeResp::getNum));
                                    ytr.setNum(count);
                                    dateListWeek.add(ytr);
                                }
                                d.setList(dateListWeek);
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(data.getRecords()));
            RedisUtil.set("excel:data:yield:" + LoginUtil.getLoginUserId(), jsonArray);
            //RedisUtil.set("excel:data:yield:"+ 1,jsonArray);
        }
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation(value = "产量统计导出")
    @RequestMapping(value = "yield_export", method = RequestMethod.GET)
    public void yieldExport(HttpServletResponse response) throws IOException {
        JSONArray jsonArray = (JSONArray) RedisUtil.get("excel:data:yield:" + LoginUtil.getLoginUserId());
        List<YieldListResp> dataList = jsonArray.toJavaList(YieldListResp.class);
        List<List<String>> head = new ArrayList<>();
        List<String> head0 = new ArrayList<>();
        head0.add("序号");
        head.add(head0);
        List<List<Object>> list = ListUtils.newArrayList();
        if (!CollectionUtils.isEmpty(dataList)) {
            if (dataList.stream().filter(d -> StringUtil.isNotBlank(d.getProcessName())).findAny().isPresent()) {
                //process
                List<String> head1 = new ArrayList<>();
                head1.add("工序");
                head.add(head1);
            } else {
                //product
                List<String> head1 = new ArrayList<>();
                head1.add("产品名称");
                head.add(head1);
            }
            List<String> head2 = new ArrayList<>();
            head2.add("产品名称");
            head.add(head2);
            List<String> head3 = new ArrayList<>();
            head3.add("产品编号");
            head.add(head3);
            List<String> head4 = new ArrayList<>();
            head4.add("产品规格");
            head.add(head4);
            List<String> head5 = new ArrayList<>();
            head5.add("单位");
            head.add(head5);
            List<String> head6 = new ArrayList<>();
            head6.add("合计");
            head.add(head6);
            dataList.get(0).getList().forEach(t -> {
                List<String> headOther = new ArrayList<>();
                headOther.add(t.getTime());
                head.add(headOther);
            });
            for (int i = 0; i < dataList.size(); i++) {
                List<Object> data = ListUtils.newArrayList();
                data.add(dataList.get(i).getId());
                data.add(dataList.get(i).getProductName());
                data.add(dataList.get(i).getProductCode());
                data.add(dataList.get(i).getProductSpecification());
                data.add(dataList.get(i).getUnit());
                data.add(dataList.get(i).getCnt());
                dataList.get(i).getList().forEach(t -> {
                    data.add(t.getNum());
                });
                list.add(data);
            }
        }
        String fileName = "产量统计导出" + System.currentTimeMillis() + ".xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
        EasyExcel.write(response.getOutputStream()).sheet("产量统计导出数据").head(head).doWrite(list);
    }


    @UserLoginToken
    @ApiOperation(value = "员工绩效")
    @RequestMapping(value = "performance_list", method = RequestMethod.POST)
    public ResponseData performanceList(@RequestBody PerformanceListVo vo) {
        IPage<PerformanceListResp> data = workReportService.getBaseMapper().getPerformance(new Page(vo.getPage(), vo.getLimit()),
                new QueryWrapper<PerformanceListResp>()
                        .between(vo.getReportStartTimeStart() != null && vo.getReportStartTimeEnd() != null, "m.actual_start_time", vo.getReportStartTimeStart(), vo.getReportStartTimeEnd())
                        .between(vo.getReportEndTimeStart() != null && vo.getReportEndTimeEnd() != null, "m.actual_end_time", vo.getReportEndTimeStart(), vo.getReportEndTimeEnd())
                        .between(vo.getActualStartTime() != null && vo.getActualEndTime() != null, "wr.report_start_time", vo.getActualStartTime(), vo.getActualEndTime())
                        .in(!CollectionUtils.isEmpty(vo.getProduceUser()), "wr.produce_user", vo.getProduceUser())
                        .in(!CollectionUtils.isEmpty(vo.getProcess()), "p.id", vo.getProcess()).orderByDesc("wr.id"));
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            data.getRecords().forEach(d -> {
                d.setCountNum(d.getGoodProductNumber() + d.getBadProductNumber());
                if (d.getBadProductNumber() == 0) {
                    d.setPassRate("100%");
                } else {
                    BigDecimal count = BigDecimal.valueOf(d.getGoodProductNumber() + d.getBadProductNumber());
                    d.setPassRate(BigDecimal.valueOf(d.getGoodProductNumber()).divide(count, 2, RoundingMode.DOWN).multiply(BigDecimal.valueOf(100L)) + "%");
                }
            });
            OwnUtil.setInRedis(data.getRecords(), "performance:data:" + LoginUtil.getLoginUserId());
        }
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation(value = "绩效工资导出")
    @RequestMapping(value = "performance_export", method = RequestMethod.GET)
    public void performanceExport(HttpServletResponse response) throws IOException {
        JSONArray jsonArray = (JSONArray) RedisUtil.get("performance:data:" + LoginUtil.getLoginUserId());
        List<PerformanceListResp> dataList = jsonArray.toJavaList(PerformanceListResp.class);
        if (!CollectionUtils.isEmpty(dataList)) {
            AtomicInteger index = new AtomicInteger(1);
            dataList.forEach(d -> {
                d.setId(index.getAndIncrement());
            });
            String fileName = "绩效工资导出" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("绩效工资导出数据").head(PerformanceListResp.class).doWrite(dataList);
        }
    }


    @UserLoginToken
    @ApiOperation(value = "工资报表")
    @RequestMapping(value = "wagers_report_list", method = RequestMethod.POST)
    public ResponseData wagersReportList(@RequestBody PerformanceListVo vo) {
        if (!CollectionUtils.isEmpty(vo.getDepIds())) {
            if (CollectionUtils.isEmpty(vo.getProduceUser())) {
                vo.setProduceUser(new ArrayList<>());
            }
            vo.getDepIds().forEach(s -> {
                Departments dep = departmentsService.getById(Integer.valueOf(s));
                if (dep != null && StringUtil.isNotBlank(dep.getIds())) {
                    vo.getProduceUser().addAll(Arrays.asList(dep.getIds().split(",")));
                }
            });
        }
        IPage<WagersReportListResp> data = workReportService.getBaseMapper().getWagersReport(new Page(vo.getPage(), vo.getLimit())
                , new QueryWrapper<WagersReportListResp>()
                        .between(vo.getReportStartTimeStart() != null && vo.getReportStartTimeEnd() != null,
                                "m.actual_start_time", vo.getReportStartTimeStart(), vo.getReportStartTimeEnd())
                        .between(vo.getReportEndTimeStart() != null && vo.getReportEndTimeEnd() != null,
                                "m.actual_end_time", vo.getReportEndTimeStart(), vo.getReportEndTimeEnd())
                        .between(vo.getActualStartTime() != null && vo.getActualEndTime() != null,
                                "wr.report_start_time", vo.getActualStartTime(), vo.getActualEndTime())
                        .in(!CollectionUtils.isEmpty(vo.getProduceUser()), "wr.produce_user", vo.getProduceUser()));
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            data.getRecords().forEach(d -> {
                User u = userService.getOne(new QueryWrapper<User>().eq("account", d.getAccount()));
                if (StringUtil.isNotBlank(u.getOther())) {
                    d.setCustomFieldVos(customFieldService.handleCustomFieldForList(u.getOther()));
                }
            });
        }
        OwnUtil.setInRedis(data.getRecords(), "wagersReport:data:" + LoginUtil.getLoginUserId());
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation(value = "工资报表导出")
    @RequestMapping(value = "wagers_report_export", method = RequestMethod.GET)
    public void wagersReportExport(HttpServletResponse response) throws IOException {
        JSONArray jsonArray = (JSONArray) RedisUtil.get("wagersReport:data:" + LoginUtil.getLoginUserId());
        List<WagersReportListResp> dataList = jsonArray.toJavaList(WagersReportListResp.class);
        if (!CollectionUtils.isEmpty(dataList)) {
            AtomicInteger index = new AtomicInteger(1);
            dataList.forEach(d -> {
                d.setId(index.getAndIncrement());
            });
            String fileName = "工资报表导出" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("工资报表导出数据").head(WagersReportListResp.class).doWrite(dataList);
        }
    }


    @UserLoginToken
    @ApiOperation(value = "不良品项分布")
    @RequestMapping(value = "bad_product_dis", method = RequestMethod.POST)
    public ResponseData badProductDis(@RequestBody YieldListVo vo) {
        IPage<BadProductDisResp> data = workReportService.getBaseMapper().getBadProductDistribution(new Page(vo.getPage(), vo.getLimit()),
                new QueryWrapper<BadProductDisResp>().between(vo.getReportStartTimeStart() != null && vo.getReportStartTimeEnd() != null,
                                "m.actual_start_time", vo.getReportStartTimeStart(), vo.getReportStartTimeEnd())
                        .between(vo.getReportEndTimeStart() != null && vo.getReportEndTimeEnd() != null,
                                "m.actual_end_time", vo.getReportEndTimeStart(), vo.getReportEndTimeEnd())
                        .between(vo.getActualStartTime() != null && vo.getActualEndTime() != null,
                                "wr.report_start_time", vo.getActualStartTime(), vo.getActualEndTime()).gt("wr.bad_product_number", 0));
        if (vo.getActualStartTime() == null) {
            vo.setActualStartTime(new Date());
        }
        if (vo.getActualEndTime() == null) {
            vo.setActualEndTime(new Date());
        }
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            data.getRecords().forEach(d -> {
                List<YieldTimeResp> dateList = workReportService.getBaseMapper().getDateByTimeOther(TimeUtil.getDateDefaultStringTwo(vo.getActualStartTime()), TimeUtil.getDateDefaultStringTwo(vo.getActualEndTime()), d.getId());
                if (!CollectionUtils.isEmpty(dateList)) {
                    if (vo.getTimeType().equals("day") || StringUtil.isBlank(vo.getTimeType())) {
                        d.setList(dateList);
                    } else {
                        Map<String, Object> map = new HashMap<>();
                        map.put("startDate", TimeUtil.getDateDefaultStringTwo(vo.getActualStartTime()));
                        map.put("endDate", TimeUtil.getDateDefaultStringTwo(vo.getActualEndTime()));
                        try {
                            List<String> timeList = new ArrayList<>();
                            if (vo.getTimeType().equals("week")) {
                                timeList = TimeUtil.doDateByStatisticsType("week", map);
                            } else if (vo.getTimeType().equals("month")) {
                                timeList = TimeUtil.doDateByStatisticsType("month", map);
                            }
                            if (!CollectionUtils.isEmpty(timeList)) {
                                List<YieldTimeResp> dateListWeek = new ArrayList<>();
                                for (int i = 0; i < timeList.size(); i += 2) {
                                    YieldTimeResp ytr = new YieldTimeResp();
                                    ytr.setTime(timeList.get(i) + "~" + timeList.get(i + 1));
                                    List<YieldTimeResp> list1 = workReportService.getBaseMapper().getDateByTimeOther(timeList.get(i), timeList.get(i + 1), d.getId());
                                    Integer count = list1.stream().collect(Collectors.summingInt(YieldTimeResp::getNum));
                                    ytr.setNum(count);
                                    dateListWeek.add(ytr);
                                }
                                d.setList(dateListWeek);
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
            OwnUtil.setInRedis(data.getRecords(), "badProductDis:data:" + LoginUtil.getLoginUserId());
        }
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation(value = "不良品分布导出")
    @RequestMapping(value = "bad_product_dis_export", method = RequestMethod.GET)
    public void badProductDisExport(HttpServletResponse response) throws IOException {
        JSONArray jsonArray = (JSONArray) RedisUtil.get("badProductDis:data:" + 1);
        List<BadProductDisResp> dataList = jsonArray.toJavaList(BadProductDisResp.class);
        if (!CollectionUtils.isEmpty(dataList)) {
            List<List<Object>> list = ListUtils.newArrayList();
            List<List<String>> head = new ArrayList<>();
            List<String> head0 = new ArrayList<>();
            head0.add("序号");
            head.add(head0);
            if (!CollectionUtils.isEmpty(dataList)) {
                List<String> head1 = new ArrayList<>();
                head1.add("不良品项");
                head.add(head1);
                List<String> head2 = new ArrayList<>();
                head2.add("占比");
                head.add(head2);
                List<String> head3 = new ArrayList<>();
                head3.add("合计");
                head.add(head3);
                if (!CollectionUtils.isEmpty(dataList.get(0).getList())) {
                    dataList.get(0).getList().forEach(t -> {
                        List<String> headOther = new ArrayList<>();
                        headOther.add(t.getTime());
                        head.add(headOther);
                    });
                }
                for (int i = 0; i < dataList.size(); i++) {
                    List<Object> data = ListUtils.newArrayList();
                    data.add(dataList.get(i).getId());
                    data.add(dataList.get(i).getName());
                    data.add(dataList.get(i).getRate());
                    data.add(dataList.get(i).getCountNum());
                    if (!CollectionUtils.isEmpty(dataList.get(i).getList())) {
                        dataList.get(i).getList().forEach(t -> {
                            data.add(t.getNum());
                        });
                    }
                    list.add(data);
                }
            }
            String fileName = "不良品分布导出" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("不良品分布导出数据").registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).head(head).doWrite(list);
        }
    }


    @UserLoginToken
    @ApiOperation(value = "不良品项汇总")
    @RequestMapping(value = "bad_product_dis_detail", method = RequestMethod.POST)
    public ResponseData<?> badProductDisDetail(@RequestBody BadProductDisDetailVo vo) {
        String gb = "wr.id";
        if (vo.getType() != null) {
            if (vo.getType() == 1) {
                gb = "m.process_code";
            } else if (vo.getType() == 2) {
                gb = "wr.produce_user";
            } else if (vo.getType() == 3) {
                gb = "m.process_code,rbp.bad_product_id";
            } else if (vo.getType() == 4) {
                gb = "m.process_code,wr.produce_user";
            } else if (vo.getType() == 5) {
                gb = "m.product_code,rbp.bad_product_id";
            } else if (vo.getType() == 6) {
                gb = "m.process_code,wr.produce_user,rbp.bad_product_id";
            } else if (vo.getType() == 7) {
                gb = "m.work_order_code,m.product_code,m.process_code,rbp.bad_product_id";
            }
        }
        IPage<BadProductDisDetail> data = workReportService.getBaseMapper().getBadProductDisDetail(new Page(vo.getPage(), vo.getLimit()),
                new QueryWrapper<BadProductDisDetail>()
                        .like(StringUtil.isNotBlank(vo.getWorkOrderCode()), "m.work_order_code", vo.getWorkOrderCode())
                        .like(StringUtil.isNotBlank(vo.getProductCode()), "m.product_code", vo.getProductCode())
                        .like(StringUtil.isNotBlank(vo.getProductName()), "p.name", vo.getProductName())
                        .like(StringUtil.isNotBlank(vo.getProductSpecification()), "p.specification", vo.getProductSpecification())
                        .like(StringUtil.isNotBlank(vo.getProcessCode()), "m.process_code", vo.getProcessCode())
                        .eq(vo.getProcessId() != null, "p2.id", vo.getProcessId())
                        .eq(vo.getBadProductId() != null, "bp.id", vo.getBadProductId())
                        .between(vo.getReportStartTimeStart() != null && vo.getReportStartTimeEnd() != null,
                                "m.actual_start_time", vo.getReportStartTimeStart(), vo.getReportStartTimeEnd())
                        .between(vo.getReportEndTimeStart() != null && vo.getReportEndTimeEnd() != null,
                                "m.actual_end_time", vo.getReportEndTimeStart(), vo.getReportEndTimeEnd())
                        .between(vo.getActualStartTime() != null && vo.getActualEndTime() != null,
                                "wr.report_start_time", vo.getActualStartTime(), vo.getActualEndTime())
                        .orderByDesc("wr.report_end_time").groupBy(gb));
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            // List<Integer> ids = data.getRecords().stream().map(BadProductDisDetail::getId).collect(Collectors.toList());
            data.getRecords().forEach(d -> {
                List<ReportBadProduct> list = reportBadProductService.list(new QueryWrapper<ReportBadProduct>().in("work_report_id", Collections.singletonList(d.getId())).groupBy("bad_product_id"));
                if (!CollectionUtils.isEmpty(list)) {
                    List<Integer> bpIds = list.stream().map(ReportBadProduct::getBadProductId).collect(Collectors.toList());
                    List<BadProduct> bpList = badProductService.listByIds(bpIds);
                    d.setBadProductName(bpList.stream().map(BadProduct::getName).collect(Collectors.joining("|")));
                }
                // 计算不良品率
                if (d.getBadProductNumber().add(d.getGoodProductNumber()).compareTo(BigDecimal.ZERO) == 0) {
                    d.setBadRateString("0%");
                } else {
                    d.setBadRateString(d.getBadProductNumber().divide(d.getBadProductNumber().add(d.getGoodProductNumber()), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L)) + "%");
                    d.setBadRateString(d.getBadRateString().replace(".00", ""));
                }

            });
        }
        OwnUtil.setInRedis(data.getRecords(), "badProductDisDetail:data:" + LoginUtil.getLoginUserId());
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation(value = "不良品项汇总导出")
    @RequestMapping(value = "bpdd_export", method = RequestMethod.GET)
    public void bpddExport(HttpServletResponse response) throws IOException {
        JSONArray jsonArray = (JSONArray) RedisUtil.get("badProductDisDetail:data:" + LoginUtil.getLoginUserId());
        List<BadProductDisDetail> dataList = jsonArray.toJavaList(BadProductDisDetail.class);
        if (!CollectionUtils.isEmpty(dataList)) {
            String fileName = "不良品项汇总导出" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("不良品项汇总导出数据").registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).head(BadProductDisDetail.class).doWrite(dataList);
        }
    }


    @UserLoginToken
    @ApiOperation(value = "生产报表")
    @RequestMapping(value = "produce_report", method = RequestMethod.POST)
    public ResponseData<IPage<ProduceReportResp>> produceReport(@RequestBody ProduceReportListVo vo) {
        //第一次自定义搜索条件
        if (!CollectionUtils.isEmpty(vo.getCustomFieldMap())) {
            List<Integer> includeIds = customFieldService.searchCustomField(vo.getCustomFieldMap(), ObjectType.workReport.getCode());
            vo.setWorkReportIds(CollectionUtils.isEmpty(includeIds) ? Collections.singletonList(0) : includeIds);
        }
        //第二次自定义筛选
        ProduceReportListVo secondCondition = Optional.ofNullable(vo.getSearchOther()).orElse(new JSONObject()).toJavaObject(ProduceReportListVo.class);
        if (!CollectionUtils.isEmpty(secondCondition.getCustomFieldMap())) {
            List<Integer> otherIds = customFieldService.searchCustomField(secondCondition.getCustomFieldMap(), ObjectType.workReport.getCode());
            secondCondition.setWorkReportIds(CollectionUtils.isEmpty(otherIds) ? Collections.singletonList(0) : otherIds);
        }

        ProduceReportListVo searchCondition = Optional.ofNullable(BeanMergeUtil.merge(CommonConstant.PRODUCE_REPORT_MERGE_RULE, vo, secondCondition, ProduceReportListVo.class)).orElse(new ProduceReportListVo());
        searchCondition.setPage(vo.getPage());
        searchCondition.setLimit(vo.getLimit());
        IPage<ProduceReportResp> data = this.handleProduceReportData(searchCondition, searchCondition.getWorkReportIds());
        OwnUtil.setInRedis(data.getRecords(), "produceReport:data:" + LoginUtil.getLoginUserId());
        data.getRecords().forEach(i -> i.setReportTimeString(TimeUtil.cnFormatByTimeExpectDay(Long.parseLong(i.getReportTimeString()) * 1000)));
//        Page<ProduceReportResp> data = workReportService.getProduceReportList(new Page<>(vo.getPage(), vo.getLimit()), searchCondition);
        return ResponseData.success(data);
    }

//    @UserLoginToken
//    @ApiOperation(value = "生产报表")
//    @RequestMapping(value = "produce_report", method = RequestMethod.POST)
//    public ResponseData produceReport(@RequestBody ProduceReportListVo vo) {
//        if (!CollectionUtils.isEmpty(vo.getDepIds())) {
//            if (CollectionUtils.isEmpty(vo.getProduceUser())) {
//                vo.setProduceUser(new ArrayList<>());
//            }
//            vo.getDepIds().forEach(s -> {
//                Departments dep = departmentsService.getById(Integer.valueOf(s));
//                if (dep != null && StringUtil.isNotBlank(dep.getIds())) {
//                    vo.getProduceUser().addAll(Arrays.asList(dep.getIds().split(",")));
//                }
//            });
//        }
//        List<Integer> ids = new ArrayList<>();
//        if (vo.getCustomFieldSearch() != null && !vo.getCustomFieldSearch().isEmpty()) {
//            List<Object> list = MongoUtils.getSearchResult(vo.getCustomFieldSearch(), "workReport", customFieldService, mongoTemplate);
//            if (!CollectionUtils.isEmpty(list)) {
//                list.forEach(l -> {
//                    WorkReport workReport = JSONObject.parseObject(JSON.toJSONString(l)).toJavaObject(WorkReport.class);
//                    ids.add(workReport.getId());
//                });
//            } else {
//                ids.add(0);
//            }
//        }
//        Integer oriLimit = vo.getLimit();
//        if (Objects.nonNull(vo.getSearchOther())) {
//            vo.setLimit(-1);
//        }
//        IPage<ProduceReportResp> data = handleProduceReportData(vo, ids);
//        if (!CollectionUtils.isEmpty(data.getRecords()) && vo.getSearchOther() != null && !vo.getSearchOther().isEmpty()) {
//            ProduceReportListVo voSearch = vo.getSearchOther().toJavaObject(ProduceReportListVo.class);
//            if (voSearch != null && voSearch.getCustomFieldSearch() != null && !voSearch.getCustomFieldSearch().isEmpty()) {
//                List<Object> objects = MongoUtils.getSearchResult(voSearch.getCustomFieldSearch(), "workReport", customFieldService, mongoTemplate);
//                if (!CollectionUtils.isEmpty(objects)) {
//                    objects.forEach(o -> {
//                        WorkReport workReport = JSONObject.parseObject(JSON.toJSONString(o)).toJavaObject(WorkReport.class);
//                        ids.add(workReport.getId());
//                    });
//                } else {
//                    ids.add(0);
//                }
//            }
//            List<Integer> integerList = data.getRecords().stream().map(ProduceReportResp::getId).collect(Collectors.toList());
//            List<Integer> idss = new ArrayList<>();
//            if (!CollectionUtils.isEmpty(ids) && ids.contains(0)) {
//                idss.add(0);
//            } else if (!CollectionUtils.isEmpty(ids) && integerList.containsAll(ids)) {
//                idss.addAll(ids);
//            } else if (!CollectionUtils.isEmpty(ids) && !integerList.containsAll(ids)) {
//                idss.addAll(ids.stream().filter(f -> integerList.contains(f)).collect(Collectors.toList()));
//            } else {
//                idss.addAll(integerList);
//            }
//            voSearch.setPage(vo.getPage());
//            voSearch.setLimit(oriLimit);
//            data = handleProduceReportData(voSearch, idss);
//        }
//        if (!CollectionUtils.isEmpty(data.getRecords())) {
//            data.getRecords().forEach(d -> {
//                WorkOrder wo = workOrderService.getOne(new QueryWrapper<WorkOrder>().eq("code", d.getWorkOrderCode()));
//                if (wo != null && StringUtil.isNotBlank(wo.getProcessId())) {
//                    List<String> processIds = Arrays.asList(wo.getProcessId().split(","));
//                    if (d.getProcessOrder() == 0) {
//                        d.setProcessOrder(processIds.size());
//                    }
//                }
//                if (d.getVerifyUser() != null) {
//                    User u = userService.getById(d.getVerifyUser());
//                    d.setVerifyUserName(u.getName());
//                }
//                List<CustomFieldVo> vos = new ArrayList<>();
//                if (StringUtil.isNotBlank(d.getWorkOrderOther())) {
//                    vos.addAll(customFieldService.handleCustomFieldForList(d.getWorkOrderOther()));
//                }
//                if (StringUtil.isNotBlank(d.getProductOther())) {
//                    vos.addAll(customFieldService.handleCustomFieldForList(d.getProductOther()));
//                }
//                if (StringUtil.isNotBlank(d.getProcessesOther())) {
//                    vos.addAll(customFieldService.handleCustomFieldForList(d.getProcessesOther()));
//                }
//                if (StringUtil.isNotBlank(d.getWorkReportOther())) {
//                    vos.addAll(customFieldService.handleCustomFieldForList(d.getWorkReportOther()));
//                }
//                if (StringUtil.isNotBlank(d.getUserOther())) {
//                    vos.addAll(customFieldService.handleCustomFieldForList(d.getUserOther()));
//                }
//                if (!CollectionUtils.isEmpty(vos)) {
//                    d.setCustomFieldVos(vos);
//                }
//                // 任务未开始工序实际开始结束时间置为空
//                if (Optional.ofNullable(d.getProcessState()).orElse(0) == 0) {
//                    d.setProcessActualStartTime(null);
//                    d.setProcessActualEndTime(null);
//                }
//            });
//        }
//        OwnUtil.setInRedis(data.getRecords(), "produceReport:data:" + LoginUtil.getLoginUserId());
//        data.getRecords().forEach(i -> i.setReportTimeString(TimeUtil.cnFormatByTimeExpectDay(Long.parseLong(i.getReportTimeString()) * 1000)));
//        return ResponseData.success(data);
//    }




    private IPage<ProduceReportResp> handleProduceReportData(ProduceReportListVo vo, List<Integer> ids) {
        return workReportService.getBaseMapper().getProduceReportData(new Page<>(vo.getPage(), vo.getLimit()),
                new QueryWrapper<ProduceReportResp>()
                        .like(StringUtil.isNotBlank(vo.getWorkOrderCode()), "m.work_order_code", vo.getWorkOrderCode())
                        .in(!CollectionUtils.isEmpty(vo.getWorkOrderState()), "wo.state", vo.getWorkOrderState())
                        .between(vo.getWorkOrderEndTimeStart() != null && vo.getWorkOrderEndTimeEnd() != null,
                                "wo.actual_end_time", vo.getWorkOrderEndTimeStart(), vo.getWorkOrderEndTimeEnd())
                        .between(vo.getReportStartTimeStart() != null && vo.getReportStartTimeEnd() != null,
                                "wr.report_start_time", vo.getReportStartTimeStart(), vo.getReportStartTimeEnd())
                        .between(vo.getReportEndTimeStart() != null && vo.getReportEndTimeEnd() != null,
                                "wr.report_end_time", vo.getReportEndTimeStart(), vo.getReportEndTimeEnd())
                        .between(vo.getActualStartTime() != null && vo.getActualEndTime() != null,
                                "wr.create_time", vo.getActualStartTime(), vo.getActualEndTime())
                        .like(StringUtil.isNotBlank(vo.getProductName()), "p.name", vo.getProductName())
                        .like(StringUtil.isNotBlank(vo.getProductCode()), "p.code", vo.getProductCode())
                        .in(!CollectionUtils.isEmpty(vo.getProduceUser()), "wr.produce_user", vo.getProduceUser())
                        .in(!CollectionUtils.isEmpty(vo.getProcessIds()), "p2.id", vo.getProcessIds()).orderByDesc("wr.id")
                        .like(StringUtil.isNotBlank(vo.getProductSpecification()), "p.specification", vo.getProductSpecification())
                        .between(vo.getWorkOrderStartTimeStart() != null && vo.getWorkOrderStartTimeEnd() != null, "wo.start_time", vo.getWorkOrderStartTimeStart(), vo.getWorkOrderStartTimeEnd())
                        .between(vo.getWorkOrderEndTimeStart() != null && vo.getWorkOrderEndTimeEnd() != null, "wo.end_time", vo.getWorkOrderEndTimeStart(), vo.getWorkOrderEndTimeEnd())
                        .between(vo.getWorkOrderActualStartTimeStart() != null && vo.getWorkOrderActualStartTimeEnd() != null, "wo.actual_start_time", vo.getWorkOrderActualStartTimeStart(), vo.getWorkOrderActualStartTimeEnd())
                        .like(StringUtil.isNotBlank(vo.getComment()), "wo.comment", vo.getComment())
                        .in(!CollectionUtils.isEmpty(vo.getMissionState()), "m.process_state", vo.getMissionState())
                        .between(vo.getMissionStartTimeStart() != null && vo.getMissionStartTimeEnd() != null, "m.start_time", vo.getMissionStartTimeStart(), vo.getMissionStartTimeEnd())
                        .between(vo.getMissionEndTimeStart() != null && vo.getMissionEndTimeEnd() != null, "m.end_time", vo.getMissionEndTimeStart(), vo.getMissionEndTimeEnd())
                        .between(vo.getMissionActualStartTimeStart() != null && vo.getMissionActualStartTimeEnd() != null, "m.actual_start_time", vo.getMissionActualStartTimeStart(), vo.getMissionActualStartTimeEnd())
                        .between(vo.getMissionActualEndTimeStart() != null && vo.getMissionActualEndTimeEnd() != null, "m.actual_end_time", vo.getMissionActualEndTimeStart(), vo.getMissionActualEndTimeEnd())
                        .between(vo.getVerifyTimeStart() != null && vo.getVerifyTimeEnd() != null, "wr.verify_time", vo.getVerifyTimeStart(), vo.getVerifyTimeEnd())
                        .in(!CollectionUtils.isEmpty(vo.getBadProduct()), "rbp.bad_product_id", vo.getBadProduct())
                        .eq(StringUtils.hasLength(vo.getPricing()), "wr.pricing_method", vo.getPricing())
                        .eq(Objects.nonNull(vo.getVerifyState()), "wr.verify_state", vo.getVerifyState())
                        .in(!CollectionUtils.isEmpty(vo.getVerifyUser()), "wr.verify_user", vo.getVerifyUser())
                        .in(!CollectionUtils.isEmpty(ids), "wr.id", ids).groupBy("wr.id"));
    }

    @UserLoginToken
    @ApiOperation(value = "生产报表导出")
    @RequestMapping(value = "produce_report_export", method = RequestMethod.GET)
    public void produceReportExport(HttpServletResponse response) throws IOException {
        JSONArray jsonArray = (JSONArray) RedisUtil.get("produceReport:data:" + LoginUtil.getLoginUserId());
        List<ProduceReportResp> dataList = jsonArray.toJavaList(ProduceReportResp.class);
        if (!CollectionUtils.isEmpty(dataList)) {
            AtomicInteger index = new AtomicInteger(1);
            dataList.forEach(d -> {
                d.setId(index.getAndIncrement());
            });
            String fileName = "生产报表导出" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("生产报表导出数据").registerWriteHandler(new CustomCellWriteHandler()).head(ProduceReportResp.class).doWrite(dataList);
        }
    }


    @UserLoginToken
    @ApiOperation(value = "在制品报表")
    @RequestMapping(value = "wip", method = RequestMethod.POST)
    public ResponseData wip(@RequestBody WipVo vo) {
        IPage<WipResp> data = workOrderService.wipData(vo);
        OwnUtil.setInRedis(data.getRecords(), "wip:data:" + LoginUtil.getLoginUserId());
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            List<ProcessNumberResp> list = new ArrayList<>();
            data.getRecords().forEach(d -> {
                if (Objects.nonNull(d) && Objects.nonNull(d.getList())) {
                    list.addAll(d.getList());
                }
            });
            List<String> listNew = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                    new TreeSet<>(Comparator.comparing(ProcessNumberResp::getProcessName))), ArrayList::new)).stream().map(m -> m.getProcessCode()).collect(Collectors.toList());
            data.getRecords().forEach(d -> {
                if (Objects.nonNull(d) && Objects.nonNull(d.getList())) {
                    List<ProcessNumberResp> numberRespList = new ArrayList<>();
                    for (String s : listNew) {
                        boolean exist = d.getList().stream().filter(m -> m.getProcessCode().equals(s)).findAny().isPresent();
                        if (exist) {
                            ProcessNumberResp bl = d.getList().stream().filter(f -> f.getProcessCode().equals(s)).findFirst().get();
                            if (bl != null) {
                                ProcessNumberResp pn = new ProcessNumberResp();
                                pn.setProcessName(bl.getProcessName());
                                pn.setProcessCode(bl.getProcessCode());
                                pn.setABPNumber(bl.getABPNumber());
                                pn.setBadProductNumber(bl.getBadProductNumber());
                                pn.setGoodProductNumber(bl.getGoodProductNumber());
                                pn.setOutStandingNumber(bl.getOutStandingNumber());
                                pn.setPlanedNumber(bl.getPlanedNumber());
                                numberRespList.add(pn);
                            }
                        } else {
                            ProcessNumberResp pn = new ProcessNumberResp();
                            Processes p = processesService.getOne(new QueryWrapper<Processes>().eq("code", s));
                            pn.setProcessName(p.getName());
                            pn.setProcessCode(s);
                            pn.setABPNumber(null);
                            pn.setBadProductNumber(null);
                            pn.setGoodProductNumber(null);
                            pn.setOutStandingNumber(null);
                            pn.setPlanedNumber(null);
                            numberRespList.add(pn);
                        }
                    }
                    d.setList(CollectionUtils.isEmpty(numberRespList) ? Collections.emptyList() : numberRespList);
                } else if (Objects.nonNull(d)) {
                    d.setList(Collections.emptyList());
                }
            });
        }
        return ResponseData.success(data);
    }

    @UserLoginToken
    @ApiOperation(value = "在制品报表表头")
    @RequestMapping(value = "wip_header", method = RequestMethod.POST)
    public ResponseData wipHeader(@RequestBody WipVo vo) {
        IPage<WipResp> data = workOrderService.wipData(vo);
        JSONObject jsonObject = (JSONObject) RedisUtil.get("processSet:" + LoginUtil.getLoginUserFactory());
        ProcessSetVo psVo = new ProcessSetVo();
        if (jsonObject != null && !jsonObject.isEmpty()) {
            psVo = jsonObject.toJavaObject(ProcessSetVo.class);
        }
        List<List<String>> header = new ArrayList<>();
        if (!CollectionUtils.isEmpty(data.getRecords())) {
            header = wipHeader(data.getRecords());
        } else {
            publicHeader(header);
        }
        if (psVo != null && !CollectionUtils.isEmpty(psVo.getVos())) {
            List<List<String>> headerNew = new ArrayList<>();
            List<String> vosString = psVo.getVos().stream().map(ProcessSetVo.vo::getName).collect(Collectors.toList());
            ProcessSetVo finalPsVo = psVo;
            header.forEach(h -> {
                String hString = h.stream().filter(f -> vosString.contains(f)).findAny().orElse(null);
                if (StringUtil.isNotBlank(hString)) {
                    boolean flag = finalPsVo.getVos().stream().filter(f -> f.getName().equals(hString) && f.isFlag()).findAny().isPresent();
                    if (flag) {
                        headerNew.add(h);
                    }
                } else {
                    headerNew.add(h);
                }
            });
            return ResponseData.success(headerNew);
        }
        return ResponseData.success(header);
    }

    private void publicHeader(List<List<String>> header) {
        List<String> head0 = new ArrayList<>();
        head0.add("工单编号");
        header.add(head0);
        List<String> head1 = new ArrayList<>();
        head1.add("产品名称");
        header.add(head1);
        List<String> head2 = new ArrayList<>();
        head2.add("产品编号");
        header.add(head2);
        List<String> head3 = new ArrayList<>();
        head3.add("产品规格");
        header.add(head3);
    }

    public List<List<String>> wipHeader(List<WipResp> dataList) {
        List<List<String>> header = new ArrayList<>();
        publicHeader(header);
        List<ProcessNumberResp> list = new ArrayList<>();
        dataList.forEach(d -> {
            if (Objects.nonNull(d) && Objects.nonNull(d.getList())) {
                list.addAll(d.getList());
            }
        });
        List<ProcessNumberResp> listNew = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(ProcessNumberResp::getProcessName))), ArrayList::new));
        JSONObject jo = (JSONObject) RedisUtil.get("processSet:" + LoginUtil.getLoginUserFactory());
        List<ProcessSetVo.vo> voList = new ArrayList<>();
        if (jo != null && !jo.isEmpty()) {
            ProcessSetVo v = jo.toJavaObject(ProcessSetVo.class);
            voList = v.getVos();
        } else {
            List<Processes> processes = processesService.list();
            List<ProcessSetVo.vo> voList1 = new ArrayList<>();
            processes.forEach(p -> {
                ProcessSetVo.vo v = new ProcessSetVo.vo();
                v.setName(p.getName());
                v.setFlag(false);
                voList1.add(v);
            });
            ProcessSetVo vo1 = new ProcessSetVo();
            vo1.setVos(voList1);
            jo = JSON.parseObject(JSON.toJSONString(vo1));
            RedisUtil.set("processSet:" + LoginUtil.getLoginUserFactory(), jo);
            voList = voList1;
        }
        List<ProcessSetVo.vo> finalVoList = voList;
        listNew.forEach(l -> {
            if (!CollectionUtils.isEmpty(finalVoList)) {
//                finalVoList.stream().filter(f->f.getName().equals(l.getProcessName())).forEach(f->f.setFlag(true));
                ProcessSetVo.vo v = finalVoList.stream().filter(f -> f.getName().equals(l.getProcessName())).findAny().orElse(null);
                if (v != null && v.isFlag()) {
                    List<String> head4 = new ArrayList<>();
                    head4.add(l.getProcessName());
                    head4.add("工序计划数量");
                    header.add(head4);
                    List<String> head5 = new ArrayList<>();
                    head5.add(l.getProcessName());
                    head5.add("良品数量");
                    header.add(head5);
                    List<String> head6 = new ArrayList<>();
                    head6.add(l.getProcessName());
                    head6.add("不良品数量");
                    header.add(head6);
                    List<String> head7 = new ArrayList<>();
                    head7.add(l.getProcessName());
                    head7.add("在制品数量");
                    header.add(head7);
                    List<String> head8 = new ArrayList<>();
                    head8.add(l.getProcessName());
                    head8.add("未清数量");
                    header.add(head8);
                }
            }
        });
        List<ProcessSetVo.vo> newList = finalVoList.stream().filter(f -> f.isFlag()).collect(Collectors.toList());
        newList.forEach(f -> {
            List<ProcessNumberResp> list1 = listNew.stream().filter(ff -> ff.getProcessName().equals(f.getName())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(list1)) {
                List<String> head4 = new ArrayList<>();
                head4.add(f.getName());
                head4.add("工序计划数量");
                header.add(head4);
                List<String> head5 = new ArrayList<>();
                head5.add(f.getName());
                head5.add("良品数量");
                header.add(head5);
                List<String> head6 = new ArrayList<>();
                head6.add(f.getName());
                head6.add("不良品数量");
                header.add(head6);
                List<String> head7 = new ArrayList<>();
                head7.add(f.getName());
                head7.add("在制品数量");
                header.add(head7);
                List<String> head8 = new ArrayList<>();
                head8.add(f.getName());
                head8.add("未清数量");
                header.add(head8);
            }
        });
//        if(!CollectionUtils.isEmpty(finalVoList)){
//            ProcessSetVo vo = new ProcessSetVo();
//            vo.setVos(finalVoList);
//            RedisUtil.set("processSet:"+LoginUtil.getLoginUserFactory(),JSONObject.parseObject(JSON.toJSONString(vo)));
//        }
        return header;
    }

    @UserLoginToken
    @ApiOperation(value = "在制品报表导出")
    @RequestMapping(value = "wip_export", method = RequestMethod.GET)
    public void wipExport(HttpServletResponse response, String names) throws IOException {
        JSONArray jsonArray = (JSONArray) RedisUtil.get("wip:data:" + LoginUtil.getLoginUserId());
        List<WipResp> dataList = jsonArray.toJavaList(WipResp.class);
        if (!CollectionUtils.isEmpty(dataList)) {
            List<List<String>> header = wipHeader(dataList);
            List<List<Object>> listData = wipDataHandle(dataList, header);
            String fileName = "在制品报表导出" + System.currentTimeMillis() + ".xlsx";
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
            EasyExcel.write(response.getOutputStream()).sheet("在制品报表导出数据").registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).head(header).doWrite(listData);
        }
    }

    public List<List<Object>> wipDataHandle(List<WipResp> dataList, List<List<String>> header) {
        List<ProcessNumberResp> list = new ArrayList<>();
        dataList.forEach(d -> {
            list.addAll(d.getList());
        });
        List<ProcessNumberResp> listNew = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                new TreeSet<>(Comparator.comparing(ProcessNumberResp::getProcessName))), ArrayList::new));
        List<List<Object>> listData = ListUtils.newArrayList();
        for (int i = 0; i < dataList.size(); i++) {
            List<Object> data = ListUtils.newArrayList();
            data.add(dataList.get(i).getWorkOrderCode());
            data.add(dataList.get(i).getProductName());
            data.add(dataList.get(i).getProductCode());
            data.add(dataList.get(i).getProductSpecification());
            if (CollectionUtils.isEmpty(dataList.get(i).getList())) {
                for (ProcessNumberResp l : listNew) {
                    data.add("");
                    data.add("");
                    data.add("");
                    data.add("");
                    data.add("");
                }
            } else {
                for (ProcessNumberResp l : listNew) {
                    if (dataList.get(i).getList().size() - listNew.size() <= 0) {
                        if (dataList.get(i).getList().stream().filter(m -> m.getProcessName().equals(l.getProcessName())).findAny().isPresent()) {
                            for (int j = 0; j < dataList.get(i).getList().size(); j++) {
                                if (j <= listNew.size()) {
                                    if (l.getProcessName().equals(dataList.get(i).getList().get(j).getProcessName()) && data.size() < header.size()) {
                                        data.add(dataList.get(i).getList().get(j).getPlanedNumber());
                                        data.add(dataList.get(i).getList().get(j).getGoodProductNumber());
                                        data.add(dataList.get(i).getList().get(j).getBadProductNumber());
                                        data.add(dataList.get(i).getList().get(j).getABPNumber());
                                        data.add(dataList.get(i).getList().get(j).getOutStandingNumber());
                                    }
                                }
                            }
                        } else if (data.size() <= header.size()) {
                            data.add("");
                            data.add("");
                            data.add("");
                            data.add("");
                            data.add("");
                        }
                    }
                }
            }
            listData.add(data);
        }
        return listData;
    }

    @UserLoginToken
    @ApiOperation(value = "在制品报表工序设置")
    @RequestMapping(value = "process_set", method = RequestMethod.POST)
    public ResponseData processSet(@RequestBody ProcessSetVo vo) {
        if (!CollectionUtils.isEmpty(vo.getVos())) {
            RedisUtil.set("processSet:" + LoginUtil.getLoginUserFactory(), JSONObject.parseObject(JSON.toJSONString(vo)));
        } else {
            JSONObject jo = (JSONObject) RedisUtil.get("processSet:" + LoginUtil.getLoginUserFactory());
            if (Objects.isNull(jo)) {
                return ResponseData.success(null);
            }

            ProcessSetVo processSetVo = jo.toJavaObject(ProcessSetVo.class);
            Set<String> haveProcessName = processSetVo.getVos().stream().filter(ProcessSetVo.vo::isFlag).map(ProcessSetVo.vo::getName).collect(Collectors.toSet());

            List<ProcessSetVo.vo> finalData = new ArrayList<>();
            // 获取有权限的所有工序(数量相等不变动)
            List<Processes> processesList = processesService.getPerByUserId(LoginUtil.getLoginUserFactory());
            if (!(processSetVo.getVos().size() == processesList.size())) {
                processesList.forEach(i -> finalData.add(new ProcessSetVo.vo().setName(i.getName()).setFlag(!haveProcessName.add(i.getName()))));
                processSetVo.setVos(finalData);
            }
            return ResponseData.success(processSetVo);
        }
        return ResponseData.success("success");
    }

}
